package com.rws;


import com.rws.exception.SubjectException;
import com.rws.message.LockMessage;
import com.rws.monitoring.ControlMonitor;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 操作消息的主要类
 * 需要Observer的信息和lock锁对象
 * 负责推送：
 *  1.锁消息
 *  2.无锁消息
 * @Author 谢卓才
 * @Date 2022/10/23 17:20
 */
public final class ReadWriteSubject {

    /**
     * @param lock 锁对象
     * @param observers Observer信息
     */
    public ReadWriteSubject(Lock lock, List<Observer> observers, ControlMonitor monitor){
        this.lock = lock;
        this.observers = observers;
        this.monitor = monitor;
    }

    private final List<Observer> observers;

    private final Lock lock;

    private final ControlMonitor monitor;

    /**
     * 锁形式消息转发
     */
    public Object putLockMessage(LockMessage message, String targetName){
        if(!(targetName != null && !targetName.isEmpty())){
            return null;
        }
        for (Observer observer : observers) {
            if(observer.getName().equals(targetName)){
                boolean isRelease = false;
                try {
                    if(isLockInterruptibly(lock)){
                        monitor.register(lock,Thread.currentThread());
                        lock.lockInterruptibly();
                        monitor.release(lock,Thread.currentThread());
                        isRelease = true;
                    } else {
                        lock.lock();
                    }
                    return observer.receive(message);
                } catch (InterruptedException e) {
                    //如果符合打断，从这里抛出异常
                    throw new SubjectException(e);
                } finally {
                    if(isLockInterruptibly(lock)){
                        if(isRelease){
                            lock.unlock();
                        } else {
                            monitor.release(lock,Thread.currentThread());
                        }
                    } else {
                        lock.unlock();
                    }
                }
            }
        }
        return null;
    }

    public boolean isLockInterruptibly(Lock lock){
        return monitor != null && lock instanceof ReentrantReadWriteLock.WriteLock;
    }

    /**
     * 不加锁消息转发
     * @param message
     * @param targetName
     */
    public Object putMessage(LockMessage message, String targetName){
        if(!(targetName != null && !targetName.isEmpty())){
            return null;
        }
        for (Observer observer : observers) {
            if(observer.getName().equals(targetName)){
                return observer.receive(message);
            }
        }
        return null;
    }
}
